package com.yungu.swift.order.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.fasterxml.jackson.databind.JsonNode;
import com.yungu.swift.assets.driver.model.dto.CarModelDto;
import com.yungu.swift.assets.driver.model.dto.CarModelValuationDto;
import com.yungu.swift.assets.driver.model.param.CarModelSiteParam;
import com.yungu.swift.assets.driver.model.vo.DriverSignLogVo;
import com.yungu.swift.assets.driver.service.CarModelService;
import com.yungu.swift.assets.driver.service.CarModelValuationService;
import com.yungu.swift.assets.passenger.model.dto.PassengerCouponDto;
import com.yungu.swift.assets.passenger.model.dto.PassengerDto;
import com.yungu.swift.assets.passenger.model.param.ApiPasPayCouponParam;
import com.yungu.swift.assets.passenger.service.PassengerCouponService;
import com.yungu.swift.assets.passenger.service.PassengerService;
import com.yungu.swift.autoconfig.redis.RedisCacheService;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.base.mapper.IMapper;
import com.yungu.swift.base.service.impl.BaseServiceImpl;
import com.yungu.swift.constants.CommonConstant;
import com.yungu.swift.constants.OrderConstant;
import com.yungu.swift.lbs.model.Coordinate;
import com.yungu.swift.lbs.model.DriverLocation;
import com.yungu.swift.lbs.model.vo.DrivingNearestVo;
import com.yungu.swift.lbs.service.DistanceService;
import com.yungu.swift.lbs.service.LocationService;
import com.yungu.swift.order.dao.OrderComplainMapper;
import com.yungu.swift.order.dao.OrderEvaluateMapper;
import com.yungu.swift.order.dao.OrderFareMapper;
import com.yungu.swift.order.dao.OrderMapper;
import com.yungu.swift.order.helper.CrosstownEvaluateHelper;
import com.yungu.swift.order.helper.EstimatedFareHelper;
import com.yungu.swift.order.model.dto.*;
import com.yungu.swift.order.model.param.AdminOrderAdjustFareParam;
import com.yungu.swift.order.model.param.ApiJoinCarModelParam;
import com.yungu.swift.order.model.param.ApiOrderUuidParam;
import com.yungu.swift.order.model.param.ApiValuationParam;
import com.yungu.swift.order.model.param.JoinOrderParam;
import com.yungu.swift.order.model.param.OrderEvaluateParam;
import com.yungu.swift.order.model.vo.ApiJoinValuationVo;
import com.yungu.swift.order.model.vo.CrosstownFareInfoVo;
import com.yungu.swift.order.model.vo.DriverExamineInfoVo;
import com.yungu.swift.order.model.vo.JsonOrderDetailVo;
import com.yungu.swift.order.model.vo.OrderCostItemVo;
import com.yungu.swift.order.model.vo.OrderEstimateVo;
import com.yungu.swift.order.service.OrderDetailService;
import com.yungu.swift.order.service.OrderFareService;
import com.yungu.swift.order.service.OrderOperateLogService;
import com.yungu.swift.order.service.OrderService;
import com.yungu.swift.order.thread.inform.InformThreadPoolUtil;
import com.yungu.swift.order.thread.inform.OrderEvent;
import com.yungu.swift.order.thread.inform.OrderStatusInformThread;
import com.yungu.swift.order.utils.SendMessageUtils;
import com.yungu.swift.socket.communication.message.UploadLocationMessage;
import com.yungu.swift.socket.push.model.PushContent;
import com.yungu.swift.socket.push.service.PushService;
import com.yungu.swift.system.finance.service.FinanceOrderService;
import com.yungu.swift.system.sys.model.dto.SysBusinessOrganizationDto;
import com.yungu.swift.system.sys.model.dto.SysPointSiteDto;
import com.yungu.swift.system.sys.model.dto.SysWayCalculationDto;
import com.yungu.swift.system.sys.model.dto.SysWayDto;
import com.yungu.swift.system.sys.model.vo.FenceRaisePriceVo;
import com.yungu.swift.system.sys.service.*;
import com.yungu.swift.utils.FormatUtils;
import com.yungu.swift.utils.JsonUtils;
import com.yungu.swift.utils.MapUtils;
import com.yungu.swift.utils.ParamUtil;
import com.yungu.swift.utils.StringUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static com.yungu.swift.constants.OrderConstant.ORDER_MAIN_STATUS_CANCEL;
import static com.yungu.swift.constants.OrderConstant.ORDER_MAIN_STATUS_DONE;
import static com.yungu.swift.constants.OrderConstant.ORDER_MAIN_STATUS_PAYED;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_ARRIVE;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_ARRIVED;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_GO;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_START;
import static com.yungu.swift.order.model.enums.OrderErrorEnum.ERR_CODE_NO_PRICE_RULE;
import static com.yungu.swift.order.model.enums.OrderErrorEnum.ERR_CODE_NO_RENTAL_RULE;
import static com.yungu.swift.order.service.OrderJoinService.PARCEL_FIXED_PRICE_KEY;

/**
 * Copyright © 厦门云谷互联信息科技有限公司 2018-2020 All Right Reserved
 * <p>
 * 订单费用业务逻辑处理接口实现类
 * 重写 add
 *
 * @since 2018-07-03 15:24
 */
@Service
public class OrderFareServiceImpl extends BaseServiceImpl<OrderFareDto> implements OrderFareService {
    private static final Logger logger = LoggerFactory.getLogger(OrderFareServiceImpl.class);

    @Autowired
    private RedisCacheService redisCacheService;
    @Autowired
    private OrderFareMapper orderFareMapper;
    @Autowired
    private OrderEvaluateMapper orderEvaluateMapper;
    @Autowired
    private OrderComplainMapper orderComplainMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private OrderOperateLogService orderOperateLogService;
    @Reference
    private PassengerService passengerService;
    @Reference
    private PushService pushService;
    @Reference
    private CarModelService carModelService;
    @Reference
    private CarModelValuationService carModelValuationService;
    @Reference
    private SysWayService sysWayService;
    @Reference
    private SysWayCalculationService sysWayCalculationService;
    @Reference
    private SysWayFenceService sysWayFenceService;
    @Reference
    private SysWayNightFareService sysWayNightFareService;
    @Reference
    private SysPointSiteService sysPointSiteService;
    @Reference
    private PassengerCouponService passengerCouponService;
    @Reference
    private LocationService locationService;
    @Reference
    private SysBusinessService sysBusinessService;
    @Reference
    private FinanceOrderService financeOrderService;
    @Reference
    private DistanceService distanceService;
    @Reference
    private SysBusinessOrganizationService sysBusinessOrganizationService;

    private final String EVALUATE_UUID = "EVALUATE_UUID";

    @Override
    protected IMapper<OrderFareDto> getMapper() {
        return orderFareMapper;
    }

    @Override
    public ResponseData<OrderFareDto> findByOrderUuid(String orderUuid) {
        List<OrderFareDto> list = orderFareMapper.list(MapUtils.build("orderUuid", orderUuid));
        if (list != null && list.size() > 0) {
            return ResponseData.buildSuccessResponse(list.get(0));
        }
        return ResponseData.buildSuccessResponse(new OrderFareDto());
    }

    @Override
    public ResponseData<Map<String, Object>> commonValuation(ApiValuationParam valuationParam) {
        // 出发时间
        Date departTime = valuationParam.getDepartTime();
        if (departTime == null) {
            departTime = new Date();
        }
        // 实时/预约
        int typeTime = 1;
        if (departTime.after(Date.from(Instant.now().plusMillis(30)))) {
            typeTime = 2;
        }
        // 车型
        String carModelUuid = valuationParam.getCarModelUuid();
        if (carModelUuid == null) {
            Map<String, Object> map = MapUtils.build(4);
            map.put("appid", valuationParam.getAppid());
            map.put("businessType", valuationParam.getBusinessType());
            CarModelDto carModelDto = carModelService.get(map).getData();
            if (carModelDto == null) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "该业务尚未开通");
            }
            carModelUuid = carModelDto.getUuid();
        }
        // 业务类型
        String businessUuid = sysBusinessService.getBusinessUuidByType(valuationParam.getBusinessType()).getData();
        // 计费方式
        Map<String, Object> params = MapUtils.build(8);
        params.put("appid", valuationParam.getAppid());
        params.put("carModelUuid", carModelUuid);
        params.put("areaID", valuationParam.getAdCode());
        params.put("orderTypeTime", typeTime);
        params.put("businessUuid", businessUuid);

        logger.info("--appid:" + valuationParam.getAppid() + "|carModelUuid:" + carModelUuid + "|areaID:" + valuationParam.getAdCode() + "|orderTypeTime:" + typeTime);

        CarModelValuationDto carValuationDto = carModelValuationService.getCarModel(params).getData();
        if (carValuationDto == null) {
            return ResponseData.buildErrorResponse(ERR_CODE_NO_PRICE_RULE.getCode(), ERR_CODE_NO_PRICE_RULE.getMsg());
        }
        //返回 map
        Map<String, Object> result = MapUtils.build(4);
        EstimatedFareHelper estimatedFareHelper = new EstimatedFareHelper(carValuationDto, valuationParam.getPlanTrip(),
                valuationParam.getPlanTime(), departTime);
        estimatedFareHelper = estimatedFareHelper.addStartFee()
                .addTimeLengthFee()
                .addMileageFee()
                .addNightSubsidyFee()
                .addHaulBackFee()
                .addHighPremiumFee();

        // 预估总金额
        double totalFee = EstimatedFareHelper.getDoubleValue(estimatedFareHelper.getTotalFee(), 2);
        // 预估实际金额
        double actPaid = totalFee;
        // 预估优惠金额
        Double couponMoney = 0d;
        ApiPasPayCouponParam payCouponParam = new ApiPasPayCouponParam();
        payCouponParam.setUserUuid(valuationParam.getUserUuid());
        payCouponParam.setBusinessType(valuationParam.getBusinessType());
        payCouponParam.setTotalFare(totalFee);
        payCouponParam.setOriginCityUuid(carValuationDto.getCityUuid());
        PassengerCouponDto passengerCouponDto = passengerCouponService.findMinCoupon(payCouponParam).getData();
        if (passengerCouponDto != null) {
            couponMoney = passengerCouponDto.getMoney();
            actPaid = totalFee - couponMoney;
            if (actPaid < 0) {
                actPaid = 0;
                couponMoney = totalFee;
            }
            result.put("couponMoney", EstimatedFareHelper.getDoubleValue(couponMoney, 2));
        }
        //总金额
        result.put("actPaid", EstimatedFareHelper.getDoubleValue(actPaid, 2));
        result.put("totalFare", totalFee);
        estimatedFareHelper.getCostDetail().setOrderFare(BigDecimal.valueOf(totalFee));
        result.put("costItems", EstimatedFareHelper.trans2Items(estimatedFareHelper.getCostDetail(), 2, 0d, 0d, -1d, couponMoney, 1, new CommissionDto()));
        //取消规则用
        result.put("cityUuid", carValuationDto.getCityUuid());
        //发单时用
        result.put("carModelValuationUuid", carValuationDto.getUuid());
        return ResponseData.buildSuccessResponse("获取成功", result);
    }


    @Override
    public ResponseData<Map<String, Object>> rentValuate(String passengerUuid, String appid, String priceRuleUuid) {
        Map<String, Object> paraMap = MapUtils.build("uuid", priceRuleUuid);
        paraMap.put("status", 1);
        //获取日租计价规则
        CarModelValuationDto rentPriceDto = carModelValuationService.get(paraMap).getData();
        if (rentPriceDto == null) {
            return ResponseData.buildErrorResponse(ERR_CODE_NO_RENTAL_RULE.getCode(), ERR_CODE_NO_RENTAL_RULE.getMsg());
        }
        //获取同类型实时计价规则
        Map<String, Object> map = MapUtils.build(6);
        map.put("carModelUuid", rentPriceDto.getCarModelUuid());
        map.put("cityUuid", rentPriceDto.getCityUuid());
        map.put("orderTypeTime", 1);
        map.put("appid", rentPriceDto.getAppid());
        List<CarModelValuationDto> carValuationDtos = carModelValuationService.list(map).getData();
        if (CollectionUtils.isNotEmpty(carValuationDtos)) {
            return ResponseData.buildErrorResponse(ERR_CODE_NO_PRICE_RULE.getCode(), ERR_CODE_NO_PRICE_RULE.getMsg());
        }
        CarModelValuationDto realTimePriceDto = carValuationDtos.get(0);
        //实时费用金额
        EstimatedFareHelper estimatedFareHelper = new EstimatedFareHelper(realTimePriceDto, rentPriceDto.getStartTrip(), rentPriceDto.getStartDuration(), null);
        estimatedFareHelper = estimatedFareHelper.addStartFee().addTimeLengthFee().addMileageFee();
        Double realTimeActualFare = estimatedFareHelper.getTotalFee();
        //实时费用优惠券
        PassengerCouponDto passengerCouponDto = passengerCouponService.findMinCoupon(passengerUuid,
                CommonConstant.BUSINESS_TYPE_SPEC, realTimeActualFare).getData();
        if (passengerCouponDto != null) {
            Double realTimeCouponFare = passengerCouponDto.getMoney();
            realTimeActualFare = realTimeActualFare - realTimeCouponFare;
            if (realTimeActualFare < 0) {
                realTimeActualFare = 0D;
            }
        }
        //计算金额差异
        Double differFare = FormatUtils.formatDouble(realTimeActualFare - rentPriceDto.getStartFare());
        if (differFare < 0) {
            differFare = 0D;
        }
        //日租半日租金额
        //套餐费
        Double rentTotalFare = rentPriceDto.getStartFare();
        Double rentActualFare = rentTotalFare;
        Double rentCouponFare = 0D;
        //日租半日租优惠券
        passengerCouponDto = passengerCouponService.findMinCoupon(passengerUuid, CommonConstant.BUSINESS_TYPE_SPEC,
                rentTotalFare).getData();
        if (passengerCouponDto != null) {
            rentCouponFare = passengerCouponDto.getMoney();
            rentActualFare = rentActualFare - rentCouponFare;
            if (rentActualFare < 0) {
                rentActualFare = 0D;
            }
        }
        //组装费用详情
        List<OrderCostItemVo> list = new ArrayList<>();
        if (rentTotalFare != null && rentTotalFare > 0D) {
            list.add(new OrderCostItemVo("套餐费" + "(" + rentPriceDto.getStartTrip() + "公里," + rentPriceDto.getStartDuration() / 60 + "小时)", rentTotalFare.toString(), 1, false));
        }
        if (rentCouponFare > 0d) {
            list.add(new OrderCostItemVo("优惠券", "-" + rentCouponFare, 2, true));
        }
        Map<String, Object> resultMap = MapUtils.build(8);
        resultMap.put("actPaid", FormatUtils.formatDouble(rentActualFare));
        resultMap.put("totalFare", FormatUtils.formatDouble(rentTotalFare));
        resultMap.put("costItems", list);
        //取消规则用
        resultMap.put("cityUuid", rentPriceDto.getCityUuid());
        //发单时用
        resultMap.put("carModelValuationUuid", rentPriceDto.getUuid());
        //发单时用
        resultMap.put("differFare", differFare.toString());
        return ResponseData.buildSuccessResponse("估价成功", resultMap);
    }

    @Override
    public ResponseData<ApiJoinValuationVo> joinValuation(OrderEvaluateParam orderEvaluateParam) {
        //乘车人数
        if (orderEvaluateParam.getAdultNum() < 1) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "估价失败：至少需要一位成人");
        }
        //获取路线
        SysWayDto sysWayDto = getSysWayDto(orderEvaluateParam);
        if (sysWayDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "线路未找到");
        }
        //获取路线价格
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("wayUuid", sysWayDto.getUuid());
        paramMap.put("carModelUuid", orderEvaluateParam.getCarModelUuid());
        ResponseData<SysWayCalculationDto> responseData = sysWayCalculationService.findOne(paramMap);
        SysWayCalculationDto sysWayCalculationDto = responseData.getData();
        if (sysWayCalculationDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "价格信息未找到");
        }
        ApiJoinValuationVo apiJoinValuationVo = new ApiJoinValuationVo();
        //订单费用
        Double orderFare = CrosstownEvaluateHelper.getOrderFare(orderEvaluateParam, sysWayCalculationDto);
        //夜间费
        Double nightFare = CrosstownEvaluateHelper.getNightFare(orderEvaluateParam, sysWayDto.getUuid());
        //围栏费用
        FenceRaisePriceVo fenceRaisePriceVo = CrosstownEvaluateHelper.getFenceFare(orderEvaluateParam, sysWayDto.getUuid());
        Double originRaisePrice = orderEvaluateParam.getAdultNum() * fenceRaisePriceVo.getOriginRaisePrice();
        Double destRaisePrice = orderEvaluateParam.getAdultNum() * fenceRaisePriceVo.getDestRaisePrice();
        //总价
        Double totalFare = orderFare + nightFare + originRaisePrice + destRaisePrice;
        if (totalFare < 0) {
            logger.info("线路：{}价格出现负数", sysWayDto.getUuid());
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "线路价格异常，请联系客服");
        }
        apiJoinValuationVo.setOrderFare(orderFare);
        apiJoinValuationVo.setNightRaisePrice(nightFare);
        apiJoinValuationVo.setOriginRaisePrice(originRaisePrice);
        apiJoinValuationVo.setDestRaisePrice(destRaisePrice);
        apiJoinValuationVo.setTotalFare(totalFare);
        //计算优惠券
        apiJoinValuationVo = CrosstownEvaluateHelper.calcuCouponFare(orderEvaluateParam, apiJoinValuationVo);
        //设置订单费用项
        apiJoinValuationVo = CrosstownEvaluateHelper.buildFareItem(orderEvaluateParam, sysWayCalculationDto, apiJoinValuationVo);

        return ResponseData.buildSuccessResponse("获取成功", apiJoinValuationVo);
    }

    @Override
    public ResponseData<Map<String, Object>> parcelValuation(JoinOrderParam joinOrderParam) {
        //获取路线
        ResponseData<SysWayCalculationDto> responseData = sysWayCalculationService.findOne(MapUtils.build("uuid",
                joinOrderParam.getSysWayCalculationUuid()));
        if (!responseData.isSuccess() || responseData.getData() == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "估价失败：获取路线价格失败");
        }
        SysWayCalculationDto sysWayCalculationDto = responseData.getData();
        //价格估算
        Map<String, Object> result = MapUtils.build();
        List<OrderCostItemVo> list = new ArrayList<>();
        int sort = 1;
        double parcelPrice = 0;
        double fixedPrice = 0;
        //获取带货价格
        String parcelPriceStr = sysWayCalculationDto.getParcelPrice();
        try {
            if (StringUtils.isNotEmpty(parcelPriceStr)) {
                JsonNode parcelPriceJson = JsonUtils.readNode(parcelPriceStr);
                parcelPrice = parcelPriceJson.get(joinOrderParam.getParcelVolumeCode()).asDouble();
                fixedPrice = parcelPrice;
                //如果不是一口价 价格等于一口价加上加价
                if (!PARCEL_FIXED_PRICE_KEY.equals(joinOrderParam.getParcelVolumeCode())) {
                    fixedPrice = parcelPriceJson.get(PARCEL_FIXED_PRICE_KEY).asDouble();
                    parcelPrice = parcelPrice + fixedPrice;
                }
            }
        } catch (Exception e) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "估价失败，获取线路价格异常");
        }

        list.add(new OrderCostItemVo("跨城小件费用", String.valueOf(parcelPrice), sort++, true));
        //一口价
        result.put(PARCEL_FIXED_PRICE_KEY, fixedPrice);
        //总价
        result.put("totalFare", parcelPrice);
        //实际价格
        double actPaid = parcelPrice;
        //优惠券
        if (StringUtils.isNotEmpty(joinOrderParam.getPassengerUuid())) {
            SysPointSiteDto systemPointSiteDto = sysPointSiteService.findOne(MapUtils.build("uuid",
                    joinOrderParam.getOriginSiteUuid())).getData();
            if (systemPointSiteDto != null) {
                String originCity = systemPointSiteDto.getCityName();
                String couponUuid;
                double couponFare;
                List<PassengerCouponDto> passengerCouponList = passengerCouponService.findJoinMinCoupon(joinOrderParam.getPassengerUuid(),
                        CommonConstant.BUSINESS_TYPE_PARCEL, parcelPrice, originCity).getData();
                if (passengerCouponList != null && passengerCouponList.size() > 0) {
                    PassengerCouponDto couponDto = passengerCouponList.get(0);
                    couponUuid = couponDto.getUuid();
                    couponFare = couponDto.getMoney();
                    actPaid = parcelPrice - couponFare;
                    if (actPaid < 0) {
                        actPaid = 0;
                    }
                    couponFare = EstimatedFareHelper.getDoubleValue(couponFare, 2);
                    if (couponFare > 0d) {
                        list.add(new OrderCostItemVo("优惠券", "-" + EstimatedFareHelper.getDoubleValue(couponFare, 2), sort++, true));
                        result.put("couponMoney", couponFare);
                        result.put("couponUuid", couponUuid);
                    }
                }
            }
        }
//        result.put("actPaid", EstimatedFareHelper.getDoubleValue(actPaid, 1));
        result.put("actPaid", EstimatedFareHelper.getDoubleValue(actPaid, 2));
        //价格明细
        result.put("costItems", list);
        return ResponseData.buildSuccessResponse("获取成功", result);
    }

    @Override
    public ResponseData<OrderEstimateVo> getRealtimeFare(ApiOrderUuidParam uuidParam) {
        OrderDto orderDto = orderService.get(uuidParam.getOrderUuid()).getData();
        if (orderDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单信息");
        }
        OrderEstimateVo orderEstimateVo = new OrderEstimateVo();
        if (ORDER_STATUS_GO.equals(orderDto.getSubStatus())
                || ORDER_STATUS_ARRIVE.equals(orderDto.getSubStatus())
                || ORDER_STATUS_START.equals(orderDto.getSubStatus())
                || ORDER_STATUS_ARRIVED.equals(orderDto.getSubStatus())) {
            //获取订单费用详情
            OrderFareDto orderFareDto = get(MapUtils.build("orderUuid", uuidParam.getOrderUuid())).getData();
            if (orderFareDto == null) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单费用");
            }
            //乘客未上车，则只计算超时等待费
            if (orderFareDto.getPasArrTime() == null) {
                //此处totalFee从0开始算需要加上超时等待费
                ResponseData<Map<String, Object>> waitFareAjaxList = getBeyondWaitFare(orderDto.getUuid());
                if (!waitFareAjaxList.isSuccess() || waitFareAjaxList.getData() == null) {
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, waitFareAjaxList.getMsg());
                }
                Map<String, Object> waitMap = waitFareAjaxList.getData();
                Long waitTime = ((Long) waitMap.get("waitTime")) / 60;
                Double waitFare = ((Double) waitMap.get("waitFare"));
                OrderFareDto costDetailDto = new OrderFareDto();
                costDetailDto.setWaitDuration((int) waitTime.longValue());
                costDetailDto.setWaitFare(waitFare);
                //总金额
                orderEstimateVo.setTotalFare(EstimatedFareHelper.getDoubleValue(waitFare, 2));
                orderEstimateVo.setCostItems(EstimatedFareHelper.trans2Items(costDetailDto, 0, 0d, 0d, 0d, 0d, 1, new CommissionDto()));
            }
            //其他情况走预估接口
            else {
                // 计算行驶距离
                DriverLocation driverPoint = locationService.findNewestOrderLocation(uuidParam.getOrderUuid(),
                        orderDto.getAppid()).getData();
                if (driverPoint == null) {
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取实际行驶距离有误");
                }
                // 行驶时间
                double planTimeValue = (System.currentTimeMillis() - orderFareDto.getPasArrTime().getTime()) / (60 * 1000 * 1.0);
                // 行驶时间向上取整
                int planTime = (int) Math.ceil(planTimeValue);
                //计算时间段从乘客实际上车时间开始
                ResponseData<OrderEstimateVo> getValTotalFare = valuationTotalFare(uuidParam.getOrderUuid(),
                        driverPoint.getMileage(), planTime, orderFareDto.getPasArrTime());
                if (!getValTotalFare.isSuccess() || getValTotalFare.getData() == null) {
                    return getValTotalFare;
                }
                orderEstimateVo = getValTotalFare.getData();
                orderEstimateVo.setDoingTime(planTime);
                orderEstimateVo.setLng(driverPoint.getCoordinate().getLng());
                orderEstimateVo.setLat(driverPoint.getCoordinate().getLat());
                orderEstimateVo.setTypeModule(orderDto.getTypeModule());
            }
        }
        return ResponseData.buildSuccessResponse(orderEstimateVo);
    }

    private ResponseData<OrderEstimateVo> valuationTotalFare(String orderUuid, Double planMileage, Integer planDuration, Date deparTime) {
        OrderDto orderDto = orderService.get(orderUuid).getData();
        if (orderDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单数据");
        }
        //获取计费方式
        CarModelValuationDto carValuationDto = getCarModelValuationDto(orderDto.getUuid()).getData();
        if (null == carValuationDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到车型计费方式");
        }
        //查询订单价格表 有则修改 无则增加
        OrderFareDto orderFareDto = getMapper().list(MapUtils.build("orderUuid", orderUuid)).get(0);
        if (orderFareDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单价格有误");
        }
        //返回map
        EstimatedFareHelper estimatedFareHelper = new EstimatedFareHelper(carValuationDto, planMileage, planDuration, deparTime);
        OrderFareDto costDetailDto = estimatedFareHelper.getCostDetail();
        //添加楼层费
        estimatedFareHelper.addStartFee()
                .addTimeLengthFee()
                .addMileageFee()
                .addNightSubsidyFee()
                .addHaulBackFee()
                .addHighPremiumFee()
                .addServiceFare(orderFareDto.getServiceFare());

        //此处totalFee从0开始算需要加上超时等待费
        Double waitFare = orderFareDto.getWaitFare() == null ? 0d : orderFareDto.getWaitFare();
        costDetailDto.setWaitFare(waitFare);
        costDetailDto.setWaitDuration(orderFareDto.getWaitDuration());
        double totalFee = estimatedFareHelper.getTotalFee();
        totalFee = totalFee + waitFare;
        OrderEstimateVo orderEstimateVo = new OrderEstimateVo();
        orderEstimateVo.setTotalFare(EstimatedFareHelper.getDoubleValue(totalFee, 2));
        //获取平台抽成比例
        SysBusinessOrganizationDto platform = sysBusinessOrganizationService.getPlatformCommission(orderDto.getActualDriverUuid(), orderDto.getTypeModule()).getData();
        //获取代理抽成比例
        SysBusinessOrganizationDto agency = sysBusinessOrganizationService.getAgencyCommission(orderDto.getActualDriverUuid(), orderDto.getTypeModule()).getData();
        //获取公司抽成比例
        SysBusinessOrganizationDto company = sysBusinessOrganizationService.getCompanyCommission(orderDto.getActualDriverUuid(), orderDto.getTypeModule()).getData();
        CommissionDto commissionDto = new CommissionDto();
        commissionDto.setPlatform(platform);
        commissionDto.setAgency(agency);
        commissionDto.setCompany(company);
        orderEstimateVo.setCostItems(EstimatedFareHelper.trans2Items(costDetailDto, orderDto.getTypeModule(),
                orderFareDto.getAssignDriverFare(), orderFareDto.getTip(), -1d, 0d, 2, commissionDto));
        return ResponseData.buildSuccessResponse(orderEstimateVo);
    }

    @Override
    public ResponseData<Boolean> saveTotalFare(CarModelValuationDto carValuationDto, OrderFareDto
            orderFareDto, Double planTrip, String uploadText, OrderDetailDto orderDetailDto) {
        if (StringUtils.isNull(planTrip)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "行驶里程不能为空");
        }
        if (null == carValuationDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到车型计费方式");
        }
        Date pasArrTime = orderFareDto.getPasArrTime();
        if (null == pasArrTime) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到乘客上车时间");
        }
        Date departTime = orderDetailDto.getDeparTime();
        if (null == departTime) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到司机出发时间");
        }
        Date date = new Date();
        // 行驶时间向上取整
        int planTime = (int) Math.ceil((date.getTime() - pasArrTime.getTime()) / (60 * 1000 * 1.0));
        EstimatedFareHelper estimatedFareHelper = new EstimatedFareHelper(carValuationDto, planTrip, planTime, pasArrTime);
        OrderFareDto costDetailDto = estimatedFareHelper.getCostDetail();
        costDetailDto.setPasArrTime(pasArrTime);

        if (carValuationDto.getOrderTypeTime() != CommonConstant.TYPE_TIME_DAILY_RENTAL
                && carValuationDto.getOrderTypeTime() != CommonConstant.TYPE_TIME_HALF_DAILY_RENTAL) {
            //回空费
            estimatedFareHelper.addStartFee()
                    .addTimeLengthFee()
                    .addMileageFee()
                    .addNightSubsidyFee()
                    .addHaulBackFee()
                    .addHighPremiumFee()
                    .addServiceFare(orderFareDto.getServiceFare());
        } else {
            estimatedFareHelper.addStartFee()
                    .addTimeLengthFee()
                    .addMileageFee()
                    .addNightSubsidyFee()
                    .addHighPremiumFee()
                    .addServiceFare(orderFareDto.getServiceFare());
        }

        double totalFee = estimatedFareHelper.getTotalFee();
        double waitFare = orderFareDto.getWaitFare() == null ? 0 : orderFareDto.getWaitFare();
        //到达目的地，根据上下车点计算规划里程；由规划里程，计算规划费用
        costDetailDto = saveMeasureInfo(carValuationDto, costDetailDto, orderDetailDto, uploadText);
        //增加或者修改orderFare表int
        costDetailDto.setTripDistance(planTrip);
        costDetailDto.setTripDuration(planTime);
        costDetailDto.setTotalFare(totalFee + waitFare);
//        costDetailDto.setOrderFare(BigDecimal.valueOf(costDetailDto.getTotalFare()).setScale(1, BigDecimal.ROUND_HALF_UP));
        costDetailDto.setOrderFare(BigDecimal.valueOf(costDetailDto.getTotalFare()).setScale(2, BigDecimal.ROUND_HALF_UP));
        costDetailDto.setLatestOrderFare(costDetailDto.getOrderFare());
//        costDetailDto.setLatestDistance(BigDecimal.valueOf(planTrip).setScale(1, BigDecimal.ROUND_HALF_UP));
        costDetailDto.setLatestDistance(BigDecimal.valueOf(planTrip).setScale(2, BigDecimal.ROUND_HALF_UP));
        costDetailDto.setArriveTime(date);
        costDetailDto.setUuid(orderFareDto.getUuid());
        costDetailDto.setGaodeDistance(orderFareDto.getGaodeDistance());
        saveOrUpdate(costDetailDto);
        return ResponseData.buildSuccessResponse("保存乘客成功", Boolean.TRUE);
    }


    @Override
    public ResponseData<CarModelValuationDto> getCarModelValuationDto(String orderUuid) {
        OrderFareDto orderFareDto = findByOrderUuid(orderUuid).getData();
        if (orderFareDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单费用信息");
        }
        return carModelValuationService.get(orderFareDto.getCarModelValuationUuid());
    }

    @Override
    public ResponseData<Boolean> surcharge(String orderUuid, Double tip) {
        tip = tip == null ? new Double(0) : tip;
        Map<String, Object> map = MapUtils.build(2);
        map.put("orderUuid", orderUuid);
        //查询订单价格表 有则修改 无则增加
        OrderFareDto orderFareDto = orderFareMapper.list(map).get(0);
        if (orderFareDto == null) {
            orderFareDto = new OrderFareDto();
            orderFareDto.setTip(tip);
            orderFareDto.setOrderUuid(orderUuid);
            this.add(orderFareDto);
        } else {
            orderFareDto.setTip(tip);
            orderFareDto.setUpdateOn(new Date());
            this.edit(orderFareDto);
        }
        return ResponseData.buildSuccessResponse("保存空驶费成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<Boolean> updFare(String orderUuid, Double fare, Double otherFare) {
        if (StringUtils.isEmpty(orderUuid)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "保存金额失败，订单编号不能为空");
        }
        Map<String, Object> orderFareMap = MapUtils.build();
        orderFareMap.put("orderUuid", orderUuid);
        OrderFareDto orderFareDto = orderFareMapper.list(orderFareMap).get(0);
        if (orderFareDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单费用信息");
        }
        //先把起步价、行程费用、订单总金额置为null
        orderFareMapper.editForTaxi(orderUuid);
        OrderFareDto updOrderFareDto = new OrderFareDto();
        updOrderFareDto.setUuid(orderFareDto.getUuid());
        updOrderFareDto.setOrderUuid(orderUuid);
        updOrderFareDto.setOrderFare(BigDecimal.valueOf(fare));
        updOrderFareDto.setUpdateOn(new Date());
        //求总金额
        //打车费 即行程费
        double orderFare = Optional.ofNullable(fare.doubleValue()).orElse(0.0);
        //调度费
        double tip = orderFareDto.getTip() == null ? 0 : orderFareDto.getTip().doubleValue();
        //等待费
        double waitFare = orderFareDto.getWaitFare() == null ? 0 : orderFareDto.getWaitFare().doubleValue();
        //服务费
        double serviceFare = orderFareDto.getServiceFare() == null ? 0 : orderFareDto.getServiceFare().doubleValue();
        otherFare = (null == otherFare ? 0 : otherFare);
        Double totalFare = orderFare + tip + waitFare + serviceFare + otherFare;
        updOrderFareDto.setTotalFare(totalFare);
        updOrderFareDto.setConfirmTime(new Date());
        //最新订单费用
        updOrderFareDto.setLatestOrderFare(BigDecimal.valueOf(orderFare));
        //额外费用
        updOrderFareDto.setOtherFare(Integer.valueOf(otherFare.intValue()));
        this.saveOrUpdate(updOrderFareDto);
        return ResponseData.buildSuccessResponse("保存实际支付金额成功", Boolean.TRUE);

    }

    @Override
    public ResponseData<DriverSignLogVo> findExaminationList(String uuid, String startTime, String endTime) {
        Map<String, Object> map = MapUtils.build(4);
        DriverSignLogVo driverSignLogVo = new DriverSignLogVo();
        //获取服务-被投诉次数
        map.put("driverUuid", uuid);
        map.put("onWorkTime", startTime);
        map.put("offWorkTime", endTime);
        driverSignLogVo.setComplainCnt(orderComplainMapper.countDriComplain(map));
        //获取服务-平均得分
        map.clear();
        map.put("uuid", uuid);
        map.put("startTime", startTime);
        map.put("endTime", endTime);
        driverSignLogVo.setAverageScore(orderEvaluateMapper.findAverageScoreByTime(map));

        //获取订单-接单总数数
        Integer orderCount = orderMapper.findOrderCountByStatus(map);
        if (orderCount == null) {
            orderCount = 0;
        }
        //获取订单-完成订单数(已支付完成)findExaminationList
        map.put("isComplete", 1);
        Integer successOrderCount = orderMapper.findOrderCountByStatus(map);
        if (successOrderCount == null) {
            successOrderCount = 0;
        }
        String result;
        //获取订单-成单率
        if ((orderCount != 0) || (successOrderCount != 0)) {
            // 创建一个数值格式化对象
            NumberFormat numberFormat = NumberFormat.getInstance();
            // 设置精确到小数点后2位
            numberFormat.setMaximumFractionDigits(2);
            result = numberFormat.format((float) successOrderCount / (float) orderCount * 100) + "%";

            driverSignLogVo.setAllOrderCount(orderCount);
            driverSignLogVo.setSuccessOrderCount(successOrderCount);
            driverSignLogVo.setSuccessOrderRate(result);
        }

        //获取收入-订单流水（所有订单的费用）
        Double orderFlowObj = orderFareMapper.findIncomeByTime(map);
        double orderFlow = orderFlowObj == null ? 0.0 : orderFlowObj;
        BigDecimal bd = BigDecimal.valueOf(orderFlow).setScale(1,
                BigDecimal.ROUND_HALF_UP);
        driverSignLogVo.setOrderFlow(bd.doubleValue());

        //获取收入-收入流水（实际入账总额，订单流水-抽成）
//        Double incomeFlowObj = driverAccountDetailService.findIncomeByTime(uuid, startTime, endTime);
//        double incomeFlow = incomeFlowObj == null ? 0 : incomeFlowObj;
//        bd = new BigDecimal(incomeFlow).setScale(1,
//                BigDecimal.ROUND_HALF_UP);
//        driverSignLogVo.setIncomeFlow(bd.doubleValue());

        //获取收入-收入流水（实际入账总额，订单流水-抽成）
        map.clear();
        map.put("driverUuid", uuid);
        map.put("startTime", startTime);
        map.put("endTime", endTime);
        BigDecimal income = financeOrderService.findIncomeByTime(map).getData();
        driverSignLogVo.setIncomeFlow(income.doubleValue());

        return ResponseData.buildSuccessResponse(driverSignLogVo);
    }

    /**
     * 设置考核项目
     *
     * @param itemName
     * @param itemValue
     * @return
     */
    private DriverExamineInfoVo.ItemVo buildExamineItem(String itemName, String itemValue) {
        DriverExamineInfoVo.ItemVo itemVo = new DriverExamineInfoVo.ItemVo();
        itemVo.setItemName(itemName);
        itemVo.setItemValue(itemValue);
        return itemVo;
    }


    @Override
    public ResponseData<Map<String, Object>> getPasCancelFare(String orderUuid) {
        if (StringUtils.isEmpty(orderUuid)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "参数错误，订单编号不能为空");
        }
        OrderDto orderDto = orderMapper.list(MapUtils.build("uuid", orderUuid)).get(0);
        if (null == orderDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取失败，检索不到订单信息");
        }
        CarModelValuationDto carValuationDto = getCarModelValuationDto(orderDto.getUuid()).getData();
        if (null == carValuationDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取失败，检索不到车辆信息");
        }
        OrderFareDto orderFareDto = orderFareMapper.list(MapUtils.build("orderUuid", orderUuid)).get(0);
        if (orderFareDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单费用信息");
        }
        OrderDetailDto orderDetailDto = orderDetailService.get(MapUtils.build("orderUuid", orderUuid)).getData();
        if (orderDetailDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单明细");
        }
        return getPasCancelDescription(orderDto, orderDetailDto, orderFareDto, carValuationDto);
    }

    /**
     * 【专车、出租车】乘客获取取消说明
     *
     * @param orderDto        订单信息
     * @param orderDetailDto  订单附加详情
     * @param orderFareDto    订单费用
     * @param carValuationDto 车型计价放方式
     * @return
     */
    private ResponseData<Map<String, Object>> getPasCancelDescription(OrderDto orderDto, OrderDetailDto
            orderDetailDto, OrderFareDto orderFareDto, CarModelValuationDto carValuationDto) {
        if (!OrderConstant.ORDER_STATUS_ARRIVE.equals(orderDto.getSubStatus())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "订单状态异常，非待上车状态");
        }
        if (null == orderFareDto.getDriArrTime()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取消息失败，获取不到上车地点");
        }
        if (null == orderDetailDto.getDeparTime()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取消息失败，获取不到出发时间");
        }
        Date date = new Date();
        //司机到达上车地点时间
        long driArrTime = orderFareDto.getDriArrTime().getTime();
        //免费等待时长（分钟）
        long freeWaitTime = carValuationDto.getFreeWaitTime() == null ? 0 : carValuationDto.getFreeWaitTime().longValue();
        //出发时间
        long departTime = orderDetailDto.getDeparTime().getTime();
        //超出免费等待时长的费用（元/分钟）
        double beyondWaitFare = carValuationDto.getBeyondWaitFare() == null ? 0 : carValuationDto.getBeyondWaitFare();
        double waitFare = 0;
        double cancelFare = carValuationDto.getOwnCancelFare() == null ? 0 : carValuationDto.getOwnCancelFare().doubleValue();
        boolean isDriLater = false;
        //等待时长
        double waitDuration;
        if (driArrTime > departTime) {
            //司机晚于出发时间到达，超时等待时间以司机到达时间开始算起
            waitDuration = (date.getTime() - driArrTime) / (60 * 1000d);
            if (CommonConstant.TYPE_TIME_APPIONT == orderDto.getTypeTime()) {
                //如果司机迟到&预约订单，则不收取取消费用
                cancelFare = 0;
                isDriLater = true;
            }
        } else {
            //司机早于出发时间到达，超时等待时间以出发时间开始算起
            waitDuration = (date.getTime() - departTime) / (60 * 1000d);
        }
        //获取超时等待费用
        if (waitDuration > freeWaitTime) {
            //进位取整（不足一分钟以一分钟计算）
            int beyondWaitTime = (int) Math.ceil(waitDuration - freeWaitTime);
//            BigDecimal bd = BigDecimal.valueOf(beyondWaitFare * beyondWaitTime).setScale(1, BigDecimal.ROUND_HALF_UP);
            BigDecimal bd = BigDecimal.valueOf(beyondWaitFare * beyondWaitTime).setScale(2, BigDecimal.ROUND_HALF_UP);
            waitFare = bd.doubleValue();
        }

        Map<String, Object> result = MapUtils.build(8);
        if (isDriLater) {
            result.put("description", "司机迟到");
        } else {
            result.put("description", "司机已到达");
        }
        if (0 != cancelFare) {
            result.put("details", "当前取消需支付" + cancelFare + "元取消费");
        }
        if (0 != waitFare) {
            result.put("details", "当前取消需支付" + waitFare + "元超时等待费");
        }
        if (0 == cancelFare && 0 == waitFare) {
            result.put("details", "此次取消不收取取消费用");
        }
        result.put("totalFare", cancelFare + waitFare);
        return ResponseData.buildSuccessResponse("获取消息成功", result);
    }

    @Override
    public ResponseData<Map<String, Object>> getWaitFare(String orderUuid) {
        Map<String, Object> params = MapUtils.build();
        params.put("uuid", orderUuid);
        OrderDto orderDto = orderMapper.list(params).get(0);
        if (StringUtils.isNull(orderDto)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索不到订单信息");
        }
        CarModelValuationDto carValuationDto = getCarModelValuationDto(orderDto.getUuid()).getData();
        if (null == carValuationDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索不到车辆信息");
        }
        //获取司机到达上车地点时间
        params.clear();
        params.put("orderUuid", orderUuid);
        OrderFareDto orderFareDto = orderFareMapper.list(params).get(0);
        if (orderFareDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单费用");
        }
        if (null == orderFareDto.getDriArrTime()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取取消说明失败，获取不到司机到达上车地点的时间");
        }
        //出发时间
        long driverArriveTime = orderFareDto.getDriArrTime().getTime();
        //获取出发时间
        OrderDetailDto orderDetailDto = orderDetailService.get(params).getData();
        if (orderDetailDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单明细");
        }
        if (null == orderDetailDto.getDeparTime()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取取消说明失败，获取不到出发时间");
        }
        //出发时间
        long departTime = orderDetailDto.getDeparTime().getTime();
        //免费等待时长
        double freeWaitTime = carValuationDto.getFreeWaitTime() == null ? 0 : carValuationDto.getFreeWaitTime();
        return getDriCancelDescription(driverArriveTime, departTime, freeWaitTime, carValuationDto);
    }


    @Override
    public ResponseData<Map<String, Object>> getFareItems(String orderUuid, String couponUuid, int type) {
        OrderDto orderDto = orderMapper.list(MapUtils.build("uuid", orderUuid)).get(0);
        if (orderDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索不到订单信息");
        }
        //获取费用详情
        OrderFareDto orderFareDto = orderFareMapper.list(MapUtils.build("orderUuid", orderUuid)).get(0);
        if (orderFareDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单费用");
        }
        //根据计价规则取起步信息
        logger.info("-- 订单：{} 车型计价规则uuid:{} --", orderUuid, orderFareDto.getCarModelValuationUuid());
        CarModelValuationDto carValuationDto = carModelValuationService.get(orderFareDto.getCarModelValuationUuid()).getData();
        if (carValuationDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索不到计价规则");
        }
        //起步字段赋值
        orderFareDto.setStartTrip(carValuationDto.getStartTrip());
        orderFareDto.setStartDuration(carValuationDto.getStartDuration());
        Double totalFare = ParamUtil.defaultIfNull(orderFareDto.getTotalFare(), 0D);
        BigDecimal amount = orderFareDto.getLatestOrderFare();
        //判断司机端展示抽成后的价格
        CommissionDto commissionDto = null;
        if (type == 2) {
            //获取平台抽成比例
            commissionDto = new CommissionDto();
            SysBusinessOrganizationDto platform = sysBusinessOrganizationService.getPlatformCommission(orderDto.getActualDriverUuid(), orderDto.getTypeModule()).getData();
            if (platform != null && platform.getCommission() != null && platform.getCommission() > 0) {
                commissionDto.setPlatform(platform);
                if (platform.getCommissionType() == 1) {//=1 按照百分比抽成
                    amount = amount.subtract(orderFareDto.getLatestOrderFare().multiply(BigDecimal.valueOf(platform.getCommission()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP))).setScale(2, RoundingMode.HALF_UP);
                } else if (platform.getCommissionType() == 2) {//=2 抽成固定金额
                    amount = amount.subtract(BigDecimal.valueOf(platform.getCommission()));
                }
            }
            //获取代理抽成比例
            SysBusinessOrganizationDto agency = sysBusinessOrganizationService.getAgencyCommission(orderDto.getActualDriverUuid(), orderDto.getTypeModule()).getData();
            if (agency != null && agency.getCommission() != null && agency.getCommission() > 0) {
                commissionDto.setAgency(agency);
                if (agency.getCommissionType() == 1) {//=1 按照百分比抽成
                    amount = amount.subtract(orderFareDto.getLatestOrderFare().multiply(BigDecimal.valueOf(agency.getCommission()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP))).setScale(2, RoundingMode.HALF_UP);
                } else if (platform.getCommissionType() == 2) {//=2 抽成固定金额
                    amount = amount.subtract(BigDecimal.valueOf(agency.getCommission()));
                }
            }
            //获取公司抽成比例
            SysBusinessOrganizationDto company = sysBusinessOrganizationService.getCompanyCommission(orderDto.getActualDriverUuid(), orderDto.getTypeModule()).getData();
            if (company != null && company.getCommission() != null && company.getCommission() > 0) {
                commissionDto.setCompany(company);
                if (company.getCommissionType() == 1) {//=1 按照百分比抽成
                    amount = amount.subtract(orderFareDto.getLatestOrderFare().multiply(BigDecimal.valueOf(company.getCommission()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP))).setScale(2, RoundingMode.HALF_UP);
                } else if (platform.getCommissionType() == 2) {//=2 抽成固定金额
                    amount = amount.subtract(BigDecimal.valueOf(company.getCommission()));
                }
            }
        }
        totalFare = BigDecimal.valueOf(totalFare).subtract(orderFareDto.getLatestOrderFare()).add(amount).doubleValue();
        Double couponMoney = 0d;
        //没有传入的优惠券，并且订单本身已有优惠券，取订单优惠券金额
        if (orderFareDto.getCouponFare() != null && orderFareDto.getCouponFare() > 0d) {
            couponMoney = orderFareDto.getCouponFare();
        }
        //有传入优惠券，取传入的优惠券金额
        else if (!isOrderCanceled(orderDto.getSubStatus()) && couponUuid != null) {
            //获取优惠的金额
            ApiPasPayCouponParam couponParam = new ApiPasPayCouponParam();
            couponParam.setCouponUuid(couponUuid);
            couponParam.setTotalFare(totalFare);
            couponParam.setBusinessType(orderDto.getTypeModule());
            List<PassengerCouponDto> passengerCouponList = passengerCouponService.getPayCouponList(couponParam).getData();
            if (CollectionUtils.isEmpty(passengerCouponList)) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索不到优惠券信息");
            }
            couponMoney = passengerCouponList.get(0).getMoney();
        }
        //支付类型
        if (orderDto.getMainStatus().equals(ORDER_MAIN_STATUS_PAYED) || orderDto.getMainStatus().equals(ORDER_MAIN_STATUS_CANCEL)) {
            //改为取订单信息
            orderFareDto.setPayType(orderDto.getPayType());
        }
        //实付金额
        BigDecimal actualFare = BigDecimal.valueOf(totalFare).subtract(BigDecimal.valueOf(couponMoney)).setScale(2, BigDecimal.ROUND_HALF_UP);
        //优惠券抵扣金额 如果订单金额小于等于优惠券 则返回优惠券实际抵扣金额 即订单金额 否则返回优惠券面值金额
        if (actualFare.compareTo(BigDecimal.ZERO) < 1) {
            couponMoney = totalFare;
        }
        Map<String, Object> objectMap = MapUtils.build(8);
        objectMap.put("totalFare", EstimatedFareHelper.getDoubleValue(totalFare, 2));
        objectMap.put("actualFare", actualFare.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        objectMap.put("costItems", EstimatedFareHelper.trans2Items(orderFareDto, orderDto.getTypeModule(), orderFareDto.getAssignDriverFare(), orderFareDto.getTip(), orderFareDto.getCancelFare(),
                EstimatedFareHelper.getDoubleValue(couponMoney, 2), type, commissionDto));
        objectMap.put("typeTrip", orderDto.getTypeTime());
        return ResponseData.buildSuccessResponse("获取成功", objectMap);
    }

    private boolean isOrderCanceled(Integer subStatus) {
        return subStatus.toString().startsWith("9");
    }


    @Override
    public ResponseData<CrosstownFareInfoVo> crosstownFareItems(String orderUuid, Integer identity) {
        List<OrderFareDto> orderFareList = orderFareMapper.list(MapUtils.build("orderUuid", orderUuid));
        if (CollectionUtils.isEmpty(orderFareList)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取费用明细失败");
        }
        List<OrderDto> orderList = orderMapper.list(MapUtils.build("uuid", orderUuid));
        if (CollectionUtils.isEmpty(orderList)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单信息失败");
        }
        OrderFareDto orderFareDto = orderFareList.get(0);
        OrderDto orderDto = orderList.get(0);
        List<OrderCostItemVo> fareItemList = new ArrayList<>();
        int sort = 0;
        //一口价
        String orderFare = "0";
        if (orderFareDto.getOrderFare() != null) {
//            BigDecimal bigDecimal = orderFareDto.getOrderFare().setScale(1, BigDecimal.ROUND_HALF_UP);
            BigDecimal bigDecimal = orderFareDto.getOrderFare().setScale(2, BigDecimal.ROUND_HALF_UP);
            fareItemList.add(new OrderCostItemVo("一口价", bigDecimal.toString(), sort++, false, false));
        }
        //特殊区域加价
        if (checkFare(orderFareDto.getOriginRaisePrice())) {
            fareItemList.add(new OrderCostItemVo("起点特殊区域加价", "+" + BigDecimal.valueOf(orderFareDto
//                    .getOriginRaisePrice()).setScale(1, BigDecimal.ROUND_HALF_UP), sort++, false, false));
                    .getOriginRaisePrice()).setScale(2, BigDecimal.ROUND_HALF_UP), sort++, false, false));
        }
        if (checkFare(orderFareDto.getDestRaisePrice())) {
            fareItemList.add(new OrderCostItemVo("终点特殊区域加价", "+" + BigDecimal.valueOf(orderFareDto
//                    .getDestRaisePrice()).setScale(1, BigDecimal.ROUND_HALF_UP), sort++, false, false));
                    .getDestRaisePrice()).setScale(2, BigDecimal.ROUND_HALF_UP), sort++, false, false));
        }
        //夜间加价
        if (checkFare(orderFareDto.getNightRaisePrice())) {
            fareItemList.add(new OrderCostItemVo("夜间加价", "+" + BigDecimal.valueOf(orderFareDto
//                    .getNightRaisePrice()).setScale(1, BigDecimal.ROUND_HALF_UP), sort++, false, false));
                    .getNightRaisePrice()).setScale(2, BigDecimal.ROUND_HALF_UP), sort++, false, false));
        }
        //高速费
        if (checkFare(orderFareDto.getHighwayFare())) {
            fareItemList.add(new OrderCostItemVo("高速费", "+" + BigDecimal.valueOf(orderFareDto
//                    .getHighwayFare()).setScale(1, BigDecimal.ROUND_HALF_UP), sort++, false, false));
                    .getHighwayFare()).setScale(2, BigDecimal.ROUND_HALF_UP), sort++, false, false));
        }
        //超标行李费
        if (checkFare(orderFareDto.getExcessBaggageFare())) {
            fareItemList.add(new OrderCostItemVo("超标行李费", "+" + BigDecimal.valueOf(orderFareDto
//                    .getExcessBaggageFare()).setScale(1, BigDecimal.ROUND_HALF_UP), sort++, false, false));
                    .getExcessBaggageFare()).setScale(2, BigDecimal.ROUND_HALF_UP), sort++, false, false));
        }
        //其他费
        if (checkFare(orderFareDto.getOtherFare())) {
            fareItemList.add(new OrderCostItemVo("其他费", "+" + BigDecimal.valueOf(orderFareDto
//                    .getOtherFare()).setScale(1, BigDecimal.ROUND_HALF_UP), sort++, false, false));
                    .getOtherFare()).setScale(2, BigDecimal.ROUND_HALF_UP), sort++, false, false));
        }
        //超标货件加价
        if (checkFare(orderFareDto.getParcelRaisePrice())) {
            fareItemList.add(new OrderCostItemVo("超标货件加价", "+" + BigDecimal.valueOf(orderFareDto
//                    .getParcelRaisePrice()).setScale(1, BigDecimal.ROUND_HALF_UP), sort++, false, false));
                    .getParcelRaisePrice()).setScale(2, BigDecimal.ROUND_HALF_UP), sort++, false, false));
        }
        //乘客端需要显示优惠券抵扣
        if (identity == CommonConstant.USER_IDENTITY_PASSENGER && checkFare(orderFareDto.getCouponFare())) {
            fareItemList.add(new OrderCostItemVo("优惠券抵扣", "-" + BigDecimal.valueOf(orderFareDto
//                    .getCouponFare()).setScale(1, BigDecimal.ROUND_HALF_UP), sort++, true, true));
                    .getCouponFare()).setScale(2, BigDecimal.ROUND_HALF_UP), sort++, true, true));
        }
        CrosstownFareInfoVo crosstownFareInfoVo = new CrosstownFareInfoVo();
        crosstownFareInfoVo.setTotalFare(orderFareDto.getTotalFare());
        crosstownFareInfoVo.setJoinStatus(orderDto.getJoinStatus());
        crosstownFareInfoVo.setFareItemList(fareItemList);
        return ResponseData.buildSuccessResponse("获取成功", crosstownFareInfoVo);
    }

    /**
     * 判断费用非空 且大于O
     */
    private boolean checkFare(Object value) {
        if (value == null) {
            return false;
        }
        Double fare = Double.parseDouble(value.toString());
        if (fare > 0) {
            return true;
        }
        return false;
    }

    @Override
    public ResponseData<Map<String, Object>> getBeyondWaitFare(String orderUuid) {
        if (StringUtils.isEmpty(orderUuid)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "参数错误，订单编号不能为空");
        }
        OrderDto orderDto = orderMapper.list(MapUtils.build("uuid", orderUuid)).get(0);
        if (null == orderDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取失败，检索不到订单信息");
        }
        CarModelValuationDto carValuationDto = getCarModelValuationDto(orderDto.getUuid()).getData();
        if (null == carValuationDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取失败，检索不到车辆信息");
        }

        OrderFareDto orderFareDto = orderFareMapper.list(MapUtils.build("orderUuid", orderUuid)).get(0);
        if (orderFareDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单费用");
        }
        if (null == orderFareDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取失败，检索不到订单价格详情");
        }

        OrderDetailDto orderDetailDto = orderDetailService.get(MapUtils.build("orderUuid", orderUuid)).getData();
        if (orderDetailDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单明细");
        }
        if (null == orderDetailDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取失败，检索不到订单附加详情");
        }
        return getBeyondWaitFare(orderDto, orderDetailDto, orderFareDto, carValuationDto);
    }


    /**
     * 【专车、出租车】待上车的时候获取超时等待费
     * 作者：Zerrion
     *
     * @param orderDto        订单编号
     * @param orderDetailDto  订单附加详情
     * @param orderFareDto    订单费用
     * @param carValuationDto 车型计价放方式
     * @return
     */
    private ResponseData<Map<String, Object>> getBeyondWaitFare(OrderDto orderDto, OrderDetailDto
            orderDetailDto, OrderFareDto orderFareDto, CarModelValuationDto carValuationDto) {
        Map<String, Object> map = MapUtils.build();
        if (OrderConstant.ORDER_STATUS_ARRIVE.compareTo(orderDto.getSubStatus()) == 0) {

            if (null == orderFareDto.getDriArrTime()) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取超时等待费失败，获取不到上车地点");
            }
            if (null == orderDetailDto.getDeparTime()) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取超时等待费失败，获取不到出发时间");
            }
            Date date = new Date();
            //司机到达上车地点时间
            long driArrTime = orderFareDto.getDriArrTime().getTime();
            //出发时间
            long departTime = orderDetailDto.getDeparTime().getTime();
            //免费等待时长（分钟）
            double freeWaitTime = carValuationDto.getFreeWaitTime() == null ? 0 : carValuationDto.getFreeWaitTime();
            //超出免费等待时长的费用（元/分钟）
            double beyondWaitFare = carValuationDto.getBeyondWaitFare() == null ? 0 : carValuationDto.getBeyondWaitFare();
            double waitFare = 0;
            //等待时长
            double waitDuration;
            if (driArrTime > departTime) {
                //司机晚于出发时间到达，超时等待时间以司机到达时间开始算起(分钟)
                waitDuration = (date.getTime() - driArrTime) / (60 * 1000d);
            } else {
                //司机晚于出发时间到达，超时等待时间以出发时间开始算起(分钟)
                waitDuration = (date.getTime() - departTime) / (60 * 1000d);
            }
            //获取超时等待费用
            double beyondWaitTime;
            if (waitDuration > freeWaitTime) {
                beyondWaitTime = waitDuration - freeWaitTime;
                //进位取整（不足一分钟以一分钟计算）
                beyondWaitTime = Math.ceil(beyondWaitTime);
                waitFare = beyondWaitTime * beyondWaitFare;
//                BigDecimal bd = BigDecimal.valueOf(waitFare).setScale(1, BigDecimal.ROUND_HALF_UP);
                BigDecimal bd = BigDecimal.valueOf(waitFare).setScale(2, BigDecimal.ROUND_HALF_UP);
                waitFare = bd.doubleValue();
            }
            //返回等待秒数
            map.put("waitTime", (date.getTime() - driArrTime) / 1000);
            //返回等待费用
            map.put("waitFare", waitFare);
            return ResponseData.buildSuccessResponse("获取超时等待费成功", map);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取超时等待费失败，订单状态异常");
    }

    /**
     * <p>【专车、出租车】司机取消获取取消说明</p>
     *
     * @param driverArriveTime 司机到达上车地点时间
     * @param departTime       出发时间
     * @param freeWaitTime     免费等待时间
     * @param carValuationDto  车型计价放方式
     * @return
     */
    private ResponseData<Map<String, Object>> getDriCancelDescription(long driverArriveTime, long departTime,
                                                                      double freeWaitTime, CarModelValuationDto carValuationDto) {
        Date date = new Date();
        double waitTime;
        if (driverArriveTime > departTime) {
            //获取等待的分钟数
            waitTime = (date.getTime() - driverArriveTime) / (60 * 1000d);
        } else {
            //获取等待的分钟数
            waitTime = (date.getTime() - departTime) / (60 * 1000d);
        }
        Map<String, Object> dataMap = MapUtils.build();
        if (waitTime <= freeWaitTime) {
            //如果乘客未迟到（等待时长未超过免费等待时长）
            dataMap.put("description", "");
            dataMap.put("details", "");
            return ResponseData.buildSuccessResponse("获取说明成功", dataMap);
        }
        double beyondTime = waitTime - freeWaitTime;
        beyondTime = Math.ceil(beyondTime);
        double beyondWaitFare = carValuationDto.getBeyondWaitFare() == null ? 0 : carValuationDto.getBeyondWaitFare();
//        BigDecimal bd = BigDecimal.valueOf(beyondWaitFare * beyondTime).setScale(1, BigDecimal.ROUND_HALF_UP);
        BigDecimal bd = BigDecimal.valueOf(beyondWaitFare * beyondTime).setScale(2, BigDecimal.ROUND_HALF_UP);
        double waitFare = bd.doubleValue();
        dataMap.put("description", "乘客已迟到，您可取消订单");
        dataMap.put("details", "现在取消订单，乘客需支付" + waitFare + "元超时等待费");
        return ResponseData.buildSuccessResponse("获取说明成功", dataMap);
    }

    /**
     * 根据查询对象获取司机的订单流水
     *
     * @param params
     * @return
     * @author Zerrion
     */
    @Override
    public ResponseData<Double> getIncome(Map<String, Object> params) {
        Double speAndTaxiIncome = this.orderFareMapper.getSpeAndTaxiOrderIncome(params);
        Double poolIncome = this.orderFareMapper.getPoolOrderIncome(params);
        Double income = new Double(speAndTaxiIncome.doubleValue() + poolIncome.doubleValue());
        //不保留小数位
        income = BigDecimal.valueOf(income).setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
        return ResponseData.buildSuccessResponse(income);
    }

    @Override
    public ResponseData<Boolean> adjustFare(AdminOrderAdjustFareParam orderAdjustFareParam) {

        //判断当前订单子状态是否为400或者500
        String orderUuid = orderAdjustFareParam.getOrderUuid();

        //检索订单信息
        OrderDto orderDto = this.orderMapper.list(MapUtils.build("uuid", orderUuid)).get(0);
        if (orderDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索不到订单");
        }

        JsonOrderDetailVo detailVo = orderService.getOrderDetail(orderAdjustFareParam.getOrderUuid(), null).getData();
        if (detailVo != null && detailVo.getSubStatus().intValue() != OrderConstant.ORDER_STATUS_ARRIVED.intValue()
                && detailVo.getSubStatus().intValue() != OrderConstant.ORDER_STATUS_FARE_CONFIRM.intValue()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "订单状态已经发生改变，请刷新页面获取最新状态，该最新状态无法调整费用");
        }
        //修改前订单费用
        BigDecimal preLatestOrderFare = BigDecimal.valueOf(orderAdjustFareParam.getPreLatestOrderFare());
        //修改前里程
        BigDecimal preLatestDistance = BigDecimal.valueOf(orderAdjustFareParam.getPreLatestDistance());

        //修改后订单费用
        BigDecimal nowLatestOrderFare = BigDecimal.valueOf(orderAdjustFareParam.getNowLatestOrderFare());
        //修改后里程
        BigDecimal nowLatestDistance = BigDecimal.valueOf(orderAdjustFareParam.getNowLatestDistance());
        //调整幅度
//        BigDecimal adjustFare = nowLatestOrderFare.subtract(preLatestOrderFare).setScale(1, BigDecimal.ROUND_HALF_UP);
        BigDecimal adjustFare = nowLatestOrderFare.subtract(preLatestOrderFare).setScale(2, BigDecimal.ROUND_HALF_UP);

        OrderOperateLogDto orderOperateLogDto = new OrderOperateLogDto();
        orderOperateLogDto.setOrderUuid(detailVo.getUuid());
        orderOperateLogDto.setAppid(detailVo.getAppid());
        orderOperateLogDto.setType(OrderOperateLogDto.TYPE_ADJUST);
        orderOperateLogDto.setUuid(StringUtils.buildUUID());
        orderOperateLogDto.setCreateOn(new Date());
        orderOperateLogDto.setNowTotalFare(nowLatestOrderFare);
        orderOperateLogDto.setPreMainStatus(detailVo.getMainStatus());
        orderOperateLogDto.setPreSubStatus(detailVo.getSubStatus());
        orderOperateLogDto.setNowMainStatus(detailVo.getMainStatus());
        orderOperateLogDto.setNowSubStatus(detailVo.getSubStatus());
        orderOperateLogDto.setNowDistance(nowLatestDistance.doubleValue());
        orderOperateLogDto.setPreTotalFare(preLatestOrderFare);
        orderOperateLogDto.setPreDistance(preLatestDistance.doubleValue());
        orderOperateLogDto.setReason(orderAdjustFareParam.getReason());
        orderOperateLogDto.setAdjustFare(adjustFare);
        orderOperateLogDto.setCreateBy(orderAdjustFareParam.getUserUuid());

        //获取订单额外金额
        OrderFareDto orderFareDto = findByOrderUuid(orderUuid).getData();
        //高速费
        Integer highwayFare = orderFareDto.getHighwayFare() == null ? 0 : orderFareDto.getHighwayFare();
        //路桥费
        Integer roadBridgeFare = orderFareDto.getRoadBridgeFare() == null ? 0 : orderFareDto.getRoadBridgeFare();
        Integer otherFare = orderFareDto.getOtherFare() == null ? 0 : orderFareDto.getOtherFare();
        double allOthersFare = highwayFare + roadBridgeFare + otherFare;

        orderFareDto.setLatestOrderFare(nowLatestOrderFare);
        orderFareDto.setLatestDistance(nowLatestDistance);
        orderFareDto.setAdjustFare(adjustFare.doubleValue());
        orderFareDto.setAdjustReason(orderAdjustFareParam.getReason());
        orderFareDto.setAdjustUser(orderAdjustFareParam.getUserUuid());
        //重新计算总额（订单费+额外费）
        orderFareDto.setTotalFare(nowLatestOrderFare.doubleValue() + allOthersFare);
        orderFareDto.setUpdateBy(orderAdjustFareParam.getUserUuid());
        orderFareDto.setUpdateOn(new Date());
        this.saveOrUpdate(orderFareDto);

        //插入订单生命周期表
        orderOperateLogService.add(orderOperateLogDto);

        //通知消息
        InformThreadPoolUtil.execute(new OrderStatusInformThread(orderDto, nowLatestOrderFare.compareTo(BigDecimal.ZERO) == 0 ? OrderEvent.FREE : OrderEvent.CUS_CHANGE_FARE));

        try {
            //推送长链接
            PushContent pushContent;
            Map<String, Object> pushMap = MapUtils.build();
            pushMap.put("title", "后台调整费用");
            pushMap.put("typeModule", detailVo.getTypeModule());
            pushMap.put("orderUuid", orderUuid);
            pushMap.put("content", "");
            pushMap.put("totalFare", orderFareDto.getTotalFare());
            pushContent = PushContent.newInstance4Pas(detailVo.getAppid(), PushContent.ORDER_ADJUST_FARE, pushMap);
            pushService.sendMessage(detailVo.getPassengerUuid(), pushContent);
            pushContent = PushContent.newInstance4Dri(detailVo.getAppid(), PushContent.ORDER_ADJUST_FARE, pushMap);
            pushService.sendMessage(detailVo.getActualDriverUuid(), pushContent);

            //改价发送短信
            SendMessageUtils.adjustFareSend(detailVo, orderFareDto, preLatestOrderFare.doubleValue());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResponseData.buildSuccessResponse("修改订单金额成功", Boolean.TRUE);
    }


    @Override
    public ResponseData<OrderFareDto> getOrderFareDetail(String orderUuid) {
        return ResponseData.buildSuccessResponse(orderFareMapper.getOrderFareDetail(orderUuid));
    }

    @Override
    public ResponseData<Boolean> saveAdditionalFare(OrderFareDto orderFareDto) {
        List<OrderFareDto> list = orderFareMapper.list(MapUtils.build("orderUuid", orderFareDto.getOrderUuid()));
        if (CollectionUtils.isNotEmpty(list)) {
            double othersFare = orderFareDto.getHighwayFare() + orderFareDto.getRoadBridgeFare() + orderFareDto.getOtherFare();
            OrderFareDto orderFareDtoTemp = list.get(0);
            orderFareDto.setUuid(orderFareDtoTemp.getUuid());
            //额外金额计入订单总价
            double totalFare = orderFareDtoTemp.getTotalFare() == null ? 0 : orderFareDtoTemp.getTotalFare();
            orderFareDto.setTotalFare(totalFare + othersFare);
            this.saveOrUpdate(orderFareDto);
            return ResponseData.buildSuccessResponse("修改费用成功!", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "未查到订单费用！");
    }


    @Override
    public ResponseData<Boolean> saveOrUpdate(OrderFareDto fareParam) {
        int complete;
        if (StringUtils.isNotBlank(fareParam.getUuid())) {
            fareParam.setUpdateOn(new Date());
            complete = orderFareMapper.edit(fareParam);
        } else {
            fareParam.setUuid(StringUtils.buildUUID());
            fareParam.setCreateOn(new Date());
            complete = orderFareMapper.add(fareParam);
        }
        return ResponseData.buildSuccessResponse(complete > 0);
    }


    /**
     * 保存地图根据上下车点的规划里程和计算后的规划费用
     *
     * @param orderFareDto   CarModelValuationDto
     * @param orderDetailDto OrderFareDto
     * @return
     */
    private OrderFareDto saveMeasureInfo(CarModelValuationDto carValuationDto, OrderFareDto orderFareDto,
                                         OrderDetailDto orderDetailDto, String uploadText) {
        //获取上车点 上车点type值
        DriverLocation originInfo = locationService.findOrderLocationByPositionType(orderDetailDto.getOrderUuid(),
                "CKSC", carValuationDto.getAppid()).getData();
        if (originInfo == null) {
            logger.info("获取不到司机位置,orderUuid:{}", orderDetailDto.getOrderUuid());
            return orderFareDto;
        }
        Coordinate coordinate = originInfo.getCoordinate();
        DrivingNearestVo drivingNearestVO = new DrivingNearestVo();
        try {
            if (StringUtils.isNotEmpty(uploadText)) {
                UploadLocationMessage uploadLocationMessage = JsonUtils.readValue(uploadText, UploadLocationMessage.class);
                drivingNearestVO = distanceService.getDrivingNearest(String.valueOf(coordinate.getLng()),
                        String.valueOf(coordinate.getLat()), String.valueOf(uploadLocationMessage.getLng()),
                        String.valueOf(uploadLocationMessage.getLat())).getData();
            } else {
                drivingNearestVO = distanceService.getDrivingNearest(String.valueOf(coordinate.getLng()),
                        String.valueOf(coordinate.getLat()), String.valueOf(orderDetailDto.getDestLng()),
                        String.valueOf(orderDetailDto.getDestLat())).getData();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        orderFareDto.setMeasureDistance(BigDecimal.valueOf(ParamUtil.defaultIfNull(drivingNearestVO.getDistance(), 0D))
                .divide(new BigDecimal("1000"), 1, BigDecimal.ROUND_HALF_UP));
        return orderFareDto;
    }

    @Override
    public ResponseData<Boolean> rushFare(String orderUuid, String driverUuid) {
        List<OrderDto> list = orderMapper.list(MapUtils.build("uuid", orderUuid));
        if (CollectionUtils.isNotEmpty(list)) {
            if (list.get(0).getMainStatus().intValue() != ORDER_MAIN_STATUS_DONE) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "该订单不是待支付订单");
            }
            if (!driverUuid.equals(list.get(0).getActualDriverUuid())) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "非实际接单司机无操作权限");
            }
            // 取乘客信息
            PassengerDto passengerDto = passengerService.get(MapUtils.build("uuid", list.get(0).getPassengerUuid())).getData();
            if (passengerDto == null) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "查无乘客信息");
            }
            //一笔订单一小时内只允许发送一次
            String rushFareCacheKey = "rushFareMsg_" + orderUuid;
            Object obj = redisCacheService.get(rushFareCacheKey);
            if (obj != null) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "已向乘客发送催款短信，请耐心等候");
            }
            //取订单价格表
            OrderFareDto orderFareDto = get(MapUtils.build("orderUuid", orderUuid)).getData();
            if (orderFareDto == null) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "查询订单价格出错");
            }
            //发送短信
            SendMessageUtils.rushFareSend(passengerDto, orderFareDto);
            redisCacheService.set(rushFareCacheKey, Boolean.TRUE, 60L);
            return ResponseData.buildSuccessResponse("已向乘客发送催款通知", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "查无此订单");
    }

    @Override
    public ResponseData<List<Map<String, Object>>> crosstownCarLevelFareList(ApiJoinCarModelParam joinCarModelParam) {
        CarModelSiteParam carModelSiteParam = new CarModelSiteParam();
        carModelSiteParam.setBusinessType(CommonConstant.BUSINESS_TYPE_POOL);
        carModelSiteParam.setOriginUuid(joinCarModelParam.getOriginUuid());
        carModelSiteParam.setDestUuid(joinCarModelParam.getDestUuid());
        carModelSiteParam.setAppid(joinCarModelParam.getAppid());
        carModelSiteParam.setTotalPassengerNum(joinCarModelParam.getAdultNum());
        List<CarModelDto> carModelDtoList = carModelService.listCarModelByPointSite(carModelSiteParam).getData();
        if (CollectionUtils.isNotEmpty(carModelDtoList)) {
            // 获得车型计价信息
            OrderEvaluateParam evaluateParam = new OrderEvaluateParam();
            BeanUtils.copyProperties(joinCarModelParam, evaluateParam);
            evaluateParam.setPassengerUuid(joinCarModelParam.getUserUuid());
            SysWayDto sysWayDto = getSysWayDto(evaluateParam);
            if (sysWayDto == null) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "估价失败：路线异常或不存在");
            }
            Long deparTime = ParamUtil.defaultIfNull(joinCarModelParam.getDeparTime(), System.currentTimeMillis());
            if (deparTime == 0) {
                deparTime = System.currentTimeMillis();
            }
            evaluateParam.setDeparTime(new Date(deparTime));
            // 车型中带上估价信息一起返回
            List<Map<String, Object>> resultList = new LinkedList<>();
            ApiJoinValuationVo apiJoinValuationVo = new ApiJoinValuationVo();
            //夜间费
            Double nightFare = CrosstownEvaluateHelper.getNightFare(evaluateParam, sysWayDto.getUuid());
            //围栏费用
            FenceRaisePriceVo fenceRaisePriceVo = CrosstownEvaluateHelper.getFenceFare(evaluateParam, sysWayDto.getUuid());
            Double originRaisePrice = fenceRaisePriceVo.getOriginRaisePrice();
            Double destRaisePrice = fenceRaisePriceVo.getDestRaisePrice();

            apiJoinValuationVo.setNightRaisePrice(nightFare);
            apiJoinValuationVo.setOriginRaisePrice(originRaisePrice);
            apiJoinValuationVo.setDestRaisePrice(destRaisePrice);

            for (CarModelDto carModelDto : carModelDtoList) {
                //获取路线价格
                Map<String, Object> paramMap = new HashMap<>(4);
                paramMap.put("wayUuid", sysWayDto.getUuid());
                paramMap.put("carModelUuid", carModelDto.getUuid());
                ResponseData<SysWayCalculationDto> responseData = sysWayCalculationService.findOne(paramMap);
                SysWayCalculationDto sysWayCalculationDto = responseData.getData();
                if (sysWayCalculationDto == null) {
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "价格信息未找到");
                }
                //订单费用
                Double orderFare = CrosstownEvaluateHelper.getOrderFare(evaluateParam, sysWayCalculationDto);
                //总价
                Double totalFare = orderFare + nightFare + originRaisePrice + destRaisePrice;
                ApiJoinValuationVo resultValuationVo = new ApiJoinValuationVo();
                BeanUtils.copyProperties(apiJoinValuationVo, resultValuationVo);
                resultValuationVo.setOrderFare(orderFare);
                resultValuationVo.setTotalFare(totalFare);
                //计算优惠券
                resultValuationVo = CrosstownEvaluateHelper.calcuCouponFare(evaluateParam, resultValuationVo);
                //费用项
                resultValuationVo = CrosstownEvaluateHelper.buildFareItem(evaluateParam, sysWayCalculationDto, resultValuationVo);
                resultValuationVo.setEvaluateUuid(StringUtils.buildUUID());
                redisCacheService.set(EVALUATE_UUID + resultValuationVo.getEvaluateUuid(), resultValuationVo, 20L);
                Map<String, Object> objectMap = buildCarModelMap(carModelDto);
                objectMap.put("valuationVo", resultValuationVo);

                resultList.add(objectMap);
            }
            return ResponseData.buildSuccessResponse(resultList);
        }

        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "车型获取失败");
    }

    /**
     * 获取线路信息
     *
     * @param orderEvaluateParam
     * @return
     */
    private SysWayDto getSysWayDto(OrderEvaluateParam orderEvaluateParam) {
        //获取路线
        Map<String, Object> paramMap = MapUtils.build();
        paramMap.put("originSiteUuid", orderEvaluateParam.getOriginUuid());
        paramMap.put("destSiteUuid", orderEvaluateParam.getDestUuid());
        paramMap.put("state", CommonConstant.STATE_NORMAL);
        paramMap.put("appid", orderEvaluateParam.getAppid());
        return sysWayService.get(paramMap).getData();
    }

    /**
     * 设置车型返回值map
     */
    private Map<String, Object> buildCarModelMap(CarModelDto carModelDto) {
        Map<String, Object> carModelMap = new HashMap<>();
        carModelMap.put("uuid", carModelDto.getUuid());
        carModelMap.put("modelName", carModelDto.getModelName());
        carModelMap.put("imageCode", carModelDto.getImageCode());
        carModelMap.put("maxPassengerSeats", carModelDto.getMaxPassengerSeats());
        carModelMap.put("defaultLevel", carModelDto.getDefaultLevel());
        return carModelMap;
    }
}
